package com.example.friend.service.user;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.common.core.constants.CacheConstants;
import com.example.common.core.constants.Constants;
import com.example.common.core.constants.HttpConstants;
import com.example.common.core.domain.LoginUser;
import com.example.common.core.domain.Result;
import com.example.common.core.domain.vo.LoginUserVO;
import com.example.common.core.enums.ResultCode;
import com.example.common.core.enums.UserIdentity;
import com.example.common.core.enums.UserStatus;
import com.example.common.core.utils.ThreadLocalUtil;
import com.example.common.redis.RedisService;
import com.example.friend.domain.user.User;
import com.example.friend.domain.user.dto.UserDTO;
import com.example.friend.domain.user.dto.UserUpdateDTO;
import com.example.friend.domain.user.vo.UserVO;
import com.example.friend.manager.UserCacheManager;
import com.example.friend.mapper.user.UserMapper;
import com.example.security.exception.ServiceException;
import com.example.security.service.TokenService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author 23050
 * @version 1.0
 * @description: TODO
 * @date 2025/3/5 19:37
 */
@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private RedisService redisService;

    @Resource
    private UserCacheManager userCacheManager;

    @Resource
    private TokenService tokenService;

    @Value("${jwt.secret}")
    private String secret;

    //发送验证码
    @Override
    public String sentCode(UserDTO userDTO) {
        if (!checkPhone(userDTO.getPhone())){
            throw new ServiceException(ResultCode.FAILED_PHONE);
        }
        String code = RandomUtil.randomNumbers(6);
        //将验证码存到redis中,缓存5分钟
//        redisService.setCacheObject(getCodeKey(userDTO.getPhone()),code, CacheConstants.CODE_TIME, TimeUnit.MINUTES);
        //测试用一直存123456
        redisService.setCacheObject(getCodeKey(userDTO.getPhone()),"123456", CacheConstants.CODE_TIME, TimeUnit.MINUTES);
        return "123456";
    }

    //校验手机号
    private boolean checkPhone(String phone) {
        // 定义手机号的正则表达式
        Pattern regex = Pattern.compile( "^1[3-9]\\d{9}$");
        Matcher m = regex.matcher(phone);
        return m.matches();
    }

    //登录和注册功能
    @Override
    public String login(UserDTO userDTO) {
        //进行验证码的比对
        CheckCode(userDTO);
        //判断走注册还是走登录逻辑
        User user = userMapper.selectOne(new LambdaQueryWrapper<User>()
                .eq(User::getPhone, userDTO.getPhone()));
        if (user == null){
            //新用户
            //在数据库中新增用户
            user = new User();
            user.setPhone(userDTO.getPhone());
            user.setCode(userDTO.getCode());
            user.setStatus(UserStatus.Normal.getValue());
            user.setNickName(userDTO.getPhone());
            int ret = userMapper.insert(user);
            if (ret<=0){
                //新增失败了
                throw new ServiceException(ResultCode.FAILED);
            }
        }
        user = userMapper.selectOne(new LambdaQueryWrapper<User>()
                .eq(User::getPhone, userDTO.getPhone()));
        //生成jwt并返回给前端
        return tokenService.createToken(user.getUserId(),secret, UserIdentity.ORDINARY.getValue(),user.getNickName(),user.getHeadImage());
    }

    //退出登录
    @Override
    public Result logout(String token) {
        // 如果前端设置了令牌前缀，则裁剪掉前缀
        if (StrUtil.isNotEmpty(token) && token.startsWith(HttpConstants.PREFIX)) {
            token = token.replaceFirst(HttpConstants.PREFIX, StrUtil.EMPTY);
        }
        //从redis中删除键值对
        boolean logout = tokenService.deleteLoginUser(token,secret);
        if (logout){
            return new Result(ResultCode.SUCCESS.getCode(),"注销成功","");
        }
        return new Result(ResultCode.FAILED.getCode(),"注销失败","");

    }

    //获取当前登录用户的信息
    @Override
    public Result info(String token) {
        // 如果前端设置了令牌前缀，则裁剪掉前缀
        if (StrUtil.isNotEmpty(token) && token.startsWith(HttpConstants.PREFIX)) {
            token = token.replaceFirst(HttpConstants.PREFIX, StrUtil.EMPTY);
        }
        //从redis中获取loginUser
        LoginUser loginUser = tokenService.getLoginUser(token, secret);
        if (loginUser == null){
            return new Result(ResultCode.FAILED.getCode(),"当前用户已过期，请重新登录","");
        }
        LoginUserVO loginUserVO = new LoginUserVO();
        loginUserVO.setNickName(loginUser.getNickName());
        loginUserVO.setHeadImage(loginUser.getHeadImage());
        return new Result(ResultCode.SUCCESS.getCode(),"获取用户信息成功",loginUserVO);
    }

    //查询用户基本信息
    @Override
    public UserVO detail() {
        Long userId = ThreadLocalUtil.get(Constants.USER_ID,Long.class);
        if (userId==null){
            throw new ServiceException(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        //从Redis中查询
        UserVO userVO = userCacheManager.getUserById(userId);
        if (userVO == null){
            throw new ServiceException(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        return userVO;
    }

    @Override
    public int edit(UserUpdateDTO userUpdateDTO) {
        Long userId = ThreadLocalUtil.get(Constants.USER_ID,Long.class);
        if (userId==null){
            throw  new ServiceException(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        User user = userMapper.selectById(userId);
        if (user==null){
            throw new ServiceException(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        user.setNickName(userUpdateDTO.getNickName());
        user.setSex(userUpdateDTO.getSex());
        user.setSchoolName(userUpdateDTO.getSchoolName());
        user.setMajorName(userUpdateDTO.getMajorName());
        user.setPhone(userUpdateDTO.getPhone());
        user.setEmail(userUpdateDTO.getEmail());
        user.setWechat(userUpdateDTO.getWechat());
        user.setIntroduce(userUpdateDTO.getIntroduce());
        //刷新用户信息缓存
        userCacheManager.refreshUser(user);
        //刷新用户登录token缓存
        tokenService.refreshLoginUser(user.getNickName(),
                user.getHeadImage(),
                ThreadLocalUtil.get(Constants.USER_KEY,String.class));
        return userMapper.updateById(user);
    }


    //验证码的比对
    private void CheckCode(UserDTO userDTO) {
        //从redis中获取这个手机号对应的code
        String cacheCode = redisService.getCacheObject(getCodeKey(userDTO.getPhone()), String.class);
        if (StrUtil.isEmpty(cacheCode)){ //验证码无效
            throw new ServiceException(ResultCode.FAILED_CODE_OUTTIME);
        }
        if (!cacheCode.equals(userDTO.getCode())){
            throw new ServiceException(ResultCode.FAILED_CODE_ERROR);
        }
        //删除验证码
        redisService.deleteObject(getCodeKey(userDTO.getPhone()));
    }

    //拼接redis中验证码的key
    private String getCodeKey(String phone) {
        return "code:"+phone;
    }


}
